/*
 * AppointmentSpec.java
 * 
 * @version 1.0, March 6, 2011
 * CS 2340 Team 10: Cyberdyne Systems
 */
package edu.gatech.oad.cyberdoc.domain;

import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;

/**
 * Represents the properties of an appointment.
 * 
 * @author John Girata
 * @version 1.0, March 6, 2011
 */
public class AppointmentSpec implements JSONSerializable {

	/**
	 * The logger for this class.
	 */
	private static final Logger LOG;

	/**
	 * The date and time this appointment begins.
	 */
	private final Date date;

	/**
	 * The patient to whom this appointment belongs.
	 */
	private final Patient patient;

	/**
	 * The doctor requested for this appointment.
	 */
	private final Doctor doctor;

	/**
	 * The reason for this appointment.
	 */
	private final String reason;
	
	/**
	 * The reason for this appointment.
	 */
	private final TreatmentRecord treatmentRecord;
	
	static {
		LOG = Logger
		.getLogger("edu.gatech.oad.cyberdoc.database.FlatFileDatabase");
	}

	/**
	 * Constructs a new AppointmentSpec with the given properties.
	 * 
	 * @param date
	 *            The date and time this appointment begins
	 * @param patient
	 *            The patient to whom this appointment belongs
	 * @param doctor
	 *            The doctor requested for this appointment
	 * @param reason
	 *            The reason for this appointment
	 */
	public AppointmentSpec(Date date, Patient patient, Doctor doctor,
			String reason, TreatmentRecord treatmentRecord) {
		this.date = date;
		this.patient = patient;
		this.doctor = doctor;
		this.reason = reason;
		this.treatmentRecord = treatmentRecord;
	}

	/**
	 * Creates an instance of this class from a JSONObject, as required by
	 * DatabaseSerializable.
	 * 
	 * @param object
	 *            The information from the database to use to create this User
	 */
	public AppointmentSpec(JSONObject object) {
		Date date = null;
		Patient patient = null;
		Doctor doctor = null;
		String reason = null;
		TreatmentRecord treatmentRecord = null;
		
		try {
			date = new Date(object.getLong("date"));
			patient = new Patient(object.getJSONObject("patient"));
			doctor = new Doctor(object.getJSONObject("doctor"));
			reason = object.getString("reason");
			treatmentRecord = new TreatmentRecord(object.getJSONObject("treatmentRecord"));
		} catch (JSONException e) {
			LOG.log(Level.SEVERE, "Expected field not found", e);
		}
		
		this.date = date;
		this.patient = patient;
		this.doctor = doctor;
		this.reason = reason;
		this.treatmentRecord = null;
	}

	/**
	 * Determines if the appointment represented by this AppointmentSpec
	 * conflicts with another.
	 * 
	 * Two appointments are considered conflicting if they both start at the
	 * same time.
	 * 
	 * @param that
	 *            The appointment to compare against
	 * @return true if these appointments conflict, or false otherwise
	 */
	public boolean isConflicting(AppointmentSpec that) {
		return date.equals(that.date);
	}

	/**
	 * Determines if the appointment represented by this class is scheduled on
	 * the same date as the date provided.
	 * 
	 * @param date
	 *            The date in question
	 * @return true if this appointment occurs on the given date, false
	 *         otherwise
	 */
	public boolean isSameDate(Date date) {
		final Calendar one = Calendar.getInstance();
		final Calendar two = Calendar.getInstance();

		one.setTime(this.date);
		two.setTime(date);

		return isEqual(one, two, Calendar.YEAR)
				&& isEqual(one, two, Calendar.DAY_OF_YEAR);
	}

	/**
	 * Helper method to determine if a specific property of two Calendar objects
	 * is equal.
	 * 
	 * @param one
	 *            The first Calendar object
	 * @param two
	 *            The second Calendar object
	 * @param property
	 *            The property in question
	 * @return true if the property in one and two are equal, false otherwise
	 */
	private static boolean isEqual(Calendar one, Calendar two, int property) {
		return one.get(property) == two.get(property);
	}

	/**
	 * Returns a string representation of this AppointmentSpec.
	 * 
	 * @return A string representation of this AppointmentSpec.
	 */
	@Override
	public String toString() {
		return "AppointmentSpec [date=" + date + ", patient=" + patient
				+ ", doctor=" + doctor + ", reason=" + reason + "]";
	}

	/**
	 * Gets the appointment's date.
	 * 
	 * @return The appointment's date
	 */
	public Date getDate() {
		return date;
	}

	/**
	 * Serializes this object into a JSONObject.
	 * 
	 * @return The JSON representation of this class
	 */
	@Override
	public JSONObject toJSONObject() {
		final JSONObject object = new JSONObject();
		
		try {
			object.put("date", date.getTime());
			object.put("patient", patient.toJSONObject());
			object.put("doctor", doctor.toJSONObject());
			object.put("reason", reason);
		} catch (JSONException e) {
			LOG.log(Level.SEVERE, "Error building JSON representation", e);
		}
		
		return object;
	}
}
